package top.lixunda.commerce.common.core.proxy;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.stereotype.Component;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionContext;
import java.util.Enumeration;

/**
 * @author Xumda
 * @version time:2019/11/26 10:56
 * <p>
 * 代理者模式，静态代理SpringSession中的HttpSession
 * 添加方法getAttribute(String name, Class<T> zClass)
 */
@SuppressWarnings({"deprecation", "AliDeprecation", "unused", "WeakerAccess"})
@Component
public class HttpSessionProxy {

    private final HttpSession target;

    private final HttpServletRequest request;

    private ObjectMapper objectMapper;

    public HttpSessionProxy(HttpSession target, HttpServletRequest request) {
        objectMapper = new ObjectMapper();
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.registerModule(new JavaTimeModule());
        this.target = target;
        this.request = request;
    }

    public long getCreationTime() {
        return target.getCreationTime();
    }

    public String getId() {
        return target.getId();
    }

    public long getLastAccessedTime() {
        return target.getLastAccessedTime();
    }

    public ServletContext getServletContext() {
        return target.getServletContext();
    }

    public void setMaxInactiveInterval(int i) {
        target.setMaxInactiveInterval(i);
    }

    public int getMaxInactiveInterval() {
        return target.getMaxInactiveInterval();
    }

    @Deprecated
    public HttpSessionContext getSessionContext() {
        return target.getSessionContext();
    }

    public Object getAttribute(String s) {
        return target.getAttribute(s);
    }

    @SuppressWarnings("unchecked")
    public <T> T getAttribute(String s, Class<T> tClass) {
        Object object = request.getAttribute(s);
        if (object == null) {
            object = getAttribute(s);
            return objectMapper.convertValue(object, tClass);
        } else {
            return (T) object;
        }
    }

    @Deprecated
    public Object getValue(String s) {
        return target.getValue(s);
    }

    public Enumeration<String> getAttributeNames() {
        return target.getAttributeNames();
    }

    @Deprecated
    public String[] getValueNames() {
        return target.getValueNames();
    }

    public void setAttribute(String s, Object o) {
        target.setAttribute(s, o);
    }

    @Deprecated
    public void putValue(String s, Object o) {
        target.putValue(s, o);
    }

    public void removeAttribute(String s) {
        target.removeAttribute(s);
    }

    @Deprecated
    public void removeValue(String s) {
        target.removeValue(s);
    }

    public void invalidate() {
        target.invalidate();
    }

    public boolean isNew() {
        return target.isNew();
    }
}
